#include <slothttpd/config/location/file_location.hpp>
#include <slothttpd/config/server.hpp>
#include <slothttpd/stage/send_file_async.hpp>
#include <slothttpd/stage/send_file.hpp>
#include <slothttpd/http/status.hpp>

#include <cstring>

#include <boost/filesystem.hpp>
#include <boost/range/algorithm/copy.hpp>

namespace slothttpd {
namespace config {

file_location::file_location(const boost::property_tree::ptree &node, server &s, bool async) :
    base_location(node, s),
    send_file_cache_fd(node.get<bool>("send_file_cache_fd", false)),
    async_send(async)
{
}

void file_location::apply(connection_ptr c)
{
    switch (c->request.method_) {
    case http::method::get:
    case http::method::head:
        break;
        
    default:
        c->send_stock_response(http::status::method_not_allowed);
        return;
    }
    
    char full_path[PATH_MAX];
    
    // +1 for '\0';
    if (std::size_t(c->request.path.size()) + path.size() + 1 <= sizeof full_path) {
        char *cpath = boost::range::copy(c->request.path, boost::range::copy(path, full_path));
        *cpath = '\0';
    
        if (async_send) {
            c->pool.construct<stage::send_file_async>(c, full_path, *this);
        } else {
            c->pool.construct<stage::send_file>(c, full_path, *this);
        }
    } else {
        c->send_stock_response(http::status::request_uri_too_long);
    }
}

std::ostream &operator<<(std::ostream &os, const file_location &loc)
{
    os << static_cast<const base_location&>(loc)
       << "        send_file_cache_fd: " << loc.send_file_cache_fd << '\n';
    
    return os;
}

}
}
